home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 June: Reference Library / Dev.CD Jun 94.toast / Periodicals / develop / develop Issue 9 / develop 9 code / TermWindow / TermWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-06  |  33.4 KB  |  1,192 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2. **                        P R O J E C T   I N F O
  3. *******************************************************************************
  4. **
  5. **  Project Name:    SampleTermWindow
  6. **     File Name:    TermWindow.c
  7. **
  8. **   Description:    This file along with the header and resource file contain
  9. **                    the source code for a fully functional, but simple, 
  10. **                    CommToolBox terminal window.  The codes purpose is to 
  11. **                    enable developers easy access to a simple terminal window.
  12. **
  13. **                       Copyright © 1988-1991 Apple Computer, Inc.
  14. **                       All rights reserved.
  15. **
  16. *******************************************************************************
  17. **                        A U T H O R   I D E N T I T Y
  18. *******************************************************************************
  19. **
  20. **    Initials    Name
  21. **    --------    -----------------------------------------------
  22. **    CSH            Craig Hotchkiss
  23. **
  24. *******************************************************************************
  25. **                        R E V I S I O N   H I S T O R Y
  26. *******************************************************************************
  27.  
  28. ******************************************************************************/
  29.  
  30.  
  31. #ifdef DUMPFILENAME
  32.     #pragma load DUMPFILENAME
  33. #else
  34.     #include <Menus.h>
  35.     #include <CommResources.h>
  36.     #include <CTBUtilities.h>
  37.     #include <GestaltEqu.h>
  38.     #include <Terminals.h>
  39. #endif
  40.  
  41.  
  42.  
  43. #ifndef __TERMWINDOW__
  44.     #include "TermWindow.h"
  45. #endif
  46.  
  47.  
  48.  
  49. /********************************************************************************
  50.                             Useful Macros
  51. ********************************************************************************/
  52.     //Replaces the Mac routines HiWord, LoWord
  53. #define HiWrd(aLong)            (((aLong) >> 16) & 0xFFFF)    
  54. #define LoWrd(aLong)            ((aLong) & 0xFFFF)
  55.  
  56.  
  57.  
  58. /********************************************************************************
  59.     Procedure:    IsNOTAWindowProc
  60.     Purpose:    This routine makes sure that the procID is contained within our
  61.                 list of known window proc types.  
  62.     Passed:        windowProcID -- This is the window type procID. 
  63.     Returns:    false if the procID matches a known window type, true if it 
  64.                 does not.
  65. ********************************************************************************/
  66. Boolean    IsNOTAWindowProc(short windowProcID)
  67. {
  68.     switch (windowProcID) {
  69.         case documentProc:
  70.         case dBoxProc:
  71.         case plainDBox:
  72.         case altDBoxProc:
  73.         case noGrowDocProc:
  74.         case movableDBoxProc:
  75.         case zoomDocProc:
  76.         case zoomNoGrow:
  77.         case rDocProc:
  78.             return false;
  79.             break;
  80.         
  81.         default:
  82.             return true;
  83.             break;
  84.     }
  85. } /*IsNOTAWindowProc*/
  86.  
  87.  
  88.  
  89. /********************************************************************************
  90.     Procedure:    AdjustTermRect
  91.     Purpose:    This routine adjusts the right and bottom portions of the rect
  92.                     passed.  I suppose macros might be better.
  93.     Passed:        theAdjustRect -- This is a pointer to the rectangle that 
  94.                     needs adjusting.
  95.     Returns:    void
  96. ********************************************************************************/
  97. void AdjustTermRect(Rect *theAdjustRect)
  98. {
  99.     (*theAdjustRect).right -= 15;
  100.     (*theAdjustRect).bottom -= 15;
  101. } /*AdjustTermRect*/
  102.  
  103.  
  104.  
  105. /********************************************************************************
  106.     Procedure:    InitTermMgr
  107.     Purpose:    Checks via Gestalt for the manager and initializes not only the
  108.                     terminal manager, but CRM and CTB Utilities.
  109.     Passed:        void
  110.     Returns:    An OSErr indicating any problems
  111. ********************************************************************************/
  112. pascal    OSErr    InitTermMgr(void) 
  113. {
  114.     OSErr            result = noErr;
  115.     Boolean            hasCTB,
  116.                     hasCRM,
  117.                     hasTM;
  118.     long            gestaltResult;
  119.     
  120.     
  121.         //these ternary C operations do the assignments nicely here.  
  122.         //    gestaltCTBVersion    --    returns CTB version #
  123.         //    gestaltCRMAttr        --    indicates that it exists
  124.         //    gestaltTermMgrAttr    --    indicates that it exists
  125.     hasCTB  = (Gestalt(gestaltCTBVersion, &gestaltResult) ? false : gestaltResult > 0);
  126.     hasCRM = (Gestalt(gestaltCRMAttr, &gestaltResult) ? false : gestaltResult != 0);
  127.     hasTM = (Gestalt(gestaltTermMgrAttr, &gestaltResult) ? false : gestaltResult != 0);
  128.  
  129.         //Each operation here  is dependent upon successful completion of 
  130.         //    the others.  
  131.     if ((hasCTB) && (hasCRM) && (hasTM)) {
  132.         if (noErr == (result = InitCRM())) {
  133.             if (noErr == (result = InitCTBUtilities())) {
  134.                     //finally!
  135.                 if (noErr == (result = InitTM())) {
  136.                 } else {
  137.                     //OSErr at InitTM/InitTermMgr
  138.                 }
  139.             } else {
  140.                 //OSErr at InitCTBUtilities/InitTermMgr
  141.             }
  142.         } else {
  143.             //OSErr at InitCRM/InitTermMgr
  144.         }
  145.     } else {
  146.         //Must not have everthing we need.
  147.         result = -1;
  148.     }
  149.  
  150.     return (result);
  151. } /*InitTermMgr*/
  152.  
  153.  
  154.  
  155. /********************************************************************************
  156.     Procedure:    FixVertScrollTermWindow
  157.     Purpose:    Fixes the vertical scroll bar to the current window size.
  158.     Passed:        termPtr:
  159.                     A pointer to the common structure
  160.     Returns:    void
  161. ********************************************************************************/
  162. void    FixVertScrollTermWindow(TermWindowPtr termPtr)
  163. {
  164.     MoveControl(    termPtr->fVertScroll,
  165.                     ((WindowPtr)termPtr)->portRect.right - (16 - 1), 
  166.                     -1
  167.                     );
  168.     
  169.     SizeControl(    termPtr->fVertScroll, 
  170.                     16,
  171.                     (((WindowPtr)termPtr)->portRect.bottom + 1) -
  172.                     (((WindowPtr)termPtr)->portRect.top- 1) -
  173.                     (16 - 1)
  174.                     );
  175. } /*FixVertScrollTermWindow*/
  176.  
  177.  
  178.  
  179. /********************************************************************************
  180.     Procedure:    FixHorizScrollTermWindow
  181.     Purpose:    Fixes the horizontal scroll bar to the current window size.
  182.     Passed:        termPtr:
  183.                     A pointer to the common structure
  184.     Returns:    void
  185. ********************************************************************************/
  186. void    FixHorizScrollTermWindow(TermWindowPtr termPtr)
  187. {
  188.     MoveControl(    termPtr->fHorizScroll,
  189.                     ((WindowPtr)termPtr)->portRect.left - 1, 
  190.                     ((WindowPtr)termPtr)->portRect.bottom - 15
  191.                     );
  192.     
  193.     SizeControl(    termPtr->fHorizScroll,
  194.                     (((WindowPtr)termPtr)->portRect.right + 1) - 14,
  195.                     16
  196.                     );
  197. } /*FixHorizScrollTermWindow*/
  198.  
  199.  
  200.  
  201. /********************************************************************************
  202.     Procedure:    CellRectToPixelRect
  203.     Purpose:    Modifies the cell-based rectangle passed so the measurements
  204.                     become pixels.
  205.     Passed:        termPtr:
  206.                     A pointer to the common structure
  207.                 theRect:
  208.                     The rectangle to be altered
  209.     Returns:    void
  210. ********************************************************************************/
  211. void    CellRectToPixelRect(TermWindowPtr termPtr, Rect *theRect)
  212. {
  213.         //A utility that turns a 1-based cell/row arrangement into pixel
  214.         //    measurements.  The subtraction of 1 from the top and left sides 
  215.         //    perform the conversion to a zero-base and the multiplication 
  216.         //    produces the real number.
  217.     (*theRect).top = (((*theRect).top - 1) * termPtr->fTermEnvirons.cellSize.v);
  218.     (*theRect).bottom = (((*theRect).bottom) * termPtr->fTermEnvirons.cellSize.v);
  219.     
  220.     (*theRect).left = (((*theRect).left - 1) * termPtr->fTermEnvirons.cellSize.h);
  221.     (*theRect).right = (((*theRect).right) * termPtr->fTermEnvirons.cellSize.h);
  222. } /*CellRectToPixelRect*/
  223.  
  224.  
  225.  
  226. /********************************************************************************
  227.     Procedure:    TermWindowSizeInLines
  228.     Purpose:    Measure the height of the window in lines.
  229.     Passed:        termPtr:
  230.                     A pointer to the common structure
  231.     Returns:    An integer indicating the number of lines.
  232. ********************************************************************************/
  233. short    TermWindowSizeInLines(TermWindowPtr termPtr)
  234. {
  235.     short            windowSize,
  236.                     lineSize,
  237.                     pixelSize,
  238.                     ourSize;
  239.     Rect            ourRect,
  240.                     termRect;
  241.     
  242.     
  243.     termRect = (**(termPtr->fTermHandle)).termRect;
  244.     
  245.     ourRect = ((WindowPtr)termPtr)->portRect;
  246.     AdjustTermRect(&ourRect);
  247.     pixelSize = ourRect.bottom - ourRect.top;
  248.     lineSize = termPtr->fTermEnvirons.cellSize.v;
  249.  
  250.     ourSize = pixelSize / lineSize;
  251.     
  252.     if (ourSize > termPtr->fTermEnvirons.textRows) {
  253.         windowSize = termPtr->fTermEnvirons.textRows;
  254.     } else {
  255.         windowSize = ourSize;
  256.     }
  257.  
  258.     return (windowSize);
  259. } /*TermWindowSizeInLines*/
  260.  
  261.  
  262.  
  263. /********************************************************************************
  264.     Procedure:    TermWindowSizeInCols
  265.     Purpose:    Measure the height of the window in columns.
  266.     Passed:        termPtr:
  267.                     A pointer to the common structure
  268.     Returns:    An integer indicating the number of columns.
  269. ********************************************************************************/
  270. short    TermWindowSizeInCols(TermWindowPtr termPtr)
  271. {
  272.     short            windowSize,
  273.                     columnSize,
  274.                     pixelSize,
  275.                     ourSize;
  276.     Rect            ourRect,
  277.                     termRect;
  278.     
  279.     
  280.     termRect = (**(termPtr->fTermHandle)).termRect;
  281.     
  282.     ourRect = ((WindowPtr)termPtr)->portRect;
  283.     AdjustTermRect(&ourRect);
  284.     pixelSize = ourRect.right - ourRect.left;
  285.     columnSize = termPtr->fTermEnvirons.cellSize.h;
  286.  
  287.     ourSize = pixelSize / columnSize;
  288.     
  289.     if (ourSize > termPtr->fTermEnvirons.textCols) {
  290.         windowSize = termPtr->fTermEnvirons.textCols;
  291.     } else {
  292.         windowSize = ourSize;
  293.     }
  294.  
  295.     return (windowSize);
  296. } /*TermWindowSizeInCols*/
  297.  
  298.  
  299.  
  300. /********************************************************************************
  301.     Procedure:    CommonActionTermWindow
  302.     Purpose:    Modifies the control value by amount and nudges amount in the
  303.                     proper direction.
  304.     Passed:        theControl --    Handle to the control we are modifying
  305.                 amount --        Amount of modification
  306.     Returns:    amount --        reflects new control change.
  307. ********************************************************************************/
  308. pascal    void    CommonActionTermWindow(ControlHandle theControl, short *amount)
  309. {
  310.     short            controlValue,
  311.                     controlMax;
  312.     
  313.     
  314.     controlValue = GetCtlValue(theControl);
  315.     controlMax = GetCtlMax(theControl);
  316.     
  317.     *amount = controlValue - *amount;
  318.     
  319.     if (*amount < 0)
  320.         *amount = 0;
  321.     else 
  322.         if (*amount > controlMax)
  323.             *amount = controlMax;
  324.     
  325.     SetCtlValue(theControl, *amount);
  326.     
  327.     *amount = controlValue - *amount;
  328. } /*CommonActionTermWindow*/
  329.  
  330.  
  331.  
  332. /********************************************************************************
  333.     Procedure:    AdjustHorizScrollTermWindow
  334.     Purpose:    Adjusts the horiz scroll bar
  335.     Passed:        termPtr:
  336.                     A pointer to the common structure
  337.     Returns:    void
  338. ********************************************************************************/
  339. void    AdjustHorizScrollTermWindow(TermWindowPtr termPtr)
  340. {
  341.     short        oldScroll,
  342.                 newScroll,
  343.                 maxTop;
  344.     Rect        ourVisRect;
  345.  
  346.     
  347.     maxTop = (termPtr->fTermEnvirons.textCols) - 
  348.         TermWindowSizeInCols(termPtr);
  349.     
  350.     if (maxTop <= 0) {
  351.         maxTop = 0;
  352.         HiliteControl(termPtr->fHorizScroll, 255);        //inactive
  353.     } else {
  354.         if (maxTop > termPtr->fTermEnvirons.textCols) {
  355.             maxTop = termPtr->fTermEnvirons.textCols;
  356.         }
  357.         
  358.         HiliteControl(termPtr->fHorizScroll, 0);            //active
  359.     }
  360.  
  361.     SetCtlMax(termPtr->fHorizScroll, maxTop);
  362.  
  363.     ourVisRect = (**(termPtr->fTermHandle)).visRect;
  364.     CellRectToPixelRect(termPtr, &ourVisRect);
  365.     
  366.     oldScroll = ourVisRect.left - (**(termPtr->fTermHandle)).viewRect.left;
  367.     newScroll = (GetCtlValue(termPtr->fHorizScroll)) * 
  368.                     (termPtr->fTermEnvirons.cellSize.h);
  369.     
  370.     //TMScroll(termPtr->fTermHandle, (oldScroll - newScroll), 0);
  371. } /*AdjustHorizScrollTermWindow*/
  372.  
  373.  
  374.  
  375. /********************************************************************************
  376.     Procedure:    HorizScrollTextTermWindow
  377.     Purpose:    Makes sure that the control movement happens correctly and the
  378.                     text is scrolled.
  379.     Passed:        termPtr:
  380.                     A pointer to the common structure
  381.     Returns:    void
  382. ********************************************************************************/
  383. pascal    void    HorizScrollTextTermWindow(ControlHandle theControl, short part)
  384. {
  385.     short            delta,
  386.                     oldValue;
  387.     TermWindowPtr    termPtr;
  388.     
  389.     
  390.     termPtr = (TermWindowPtr)GetCRefCon(theControl);
  391.  
  392.     oldValue = GetCtlValue(termPtr->fHorizScroll);
  393.         
  394.     switch (part) {
  395.         case inUpButton:
  396.         case inDownButton:
  397.             delta = 1;
  398.             break;
  399.  
  400.         case inPageUp:
  401.         case inPageDown:
  402.             delta = TermWindowSizeInCols(termPtr);
  403.             break;
  404.         
  405.         default:
  406.             break;
  407.     }
  408.     
  409.     if (part != 0) {
  410.         if ((part == inDownButton) || (part == inPageDown)) {
  411.             delta = -delta;
  412.         }
  413.         
  414.         CommonActionTermWindow(termPtr->fHorizScroll, &delta);
  415.         
  416.         TMScroll(termPtr->fTermHandle, 
  417.             (delta) * (termPtr->fTermEnvirons.cellSize.h), 0);
  418.     }
  419. } /*HorizScrollTextTermWindow*/
  420.  
  421.  
  422.  
  423. /********************************************************************************
  424.     Procedure:    DoHorizScrollTermWindow
  425.     Purpose:    Does the horiz scroll
  426.     Passed:        termPtr --    A pointer to the common structure
  427.                 part --        What part of the scroll the user clicked in
  428.                 point --    Exact point where the click occurred
  429.     Returns:    void
  430. ********************************************************************************/
  431. void     DoHorizScrollTermWindow(TermWindowPtr termPtr, short part, Point point)
  432. {
  433.     short        controlValue;
  434.     
  435.     
  436.     if (part == inThumb) {
  437.         controlValue = GetCtlValue(termPtr->fHorizScroll);
  438.         
  439.         part = TrackControl(termPtr->fHorizScroll, point, nil);
  440.         if (part != 0) {
  441.             controlValue -= GetCtlValue(termPtr->fHorizScroll);
  442.             if (controlValue < 0) {
  443.                 TMScroll(termPtr->fTermHandle, 
  444.                     (controlValue) * (termPtr->fTermEnvirons.cellSize.h), 0
  445.                     );
  446.             }
  447.             if (controlValue > 0) {
  448.                 TMScroll(termPtr->fTermHandle,
  449.                     (controlValue) * (termPtr->fTermEnvirons.cellSize.h), 0
  450.                     );
  451.             }
  452.         }
  453.     } else {
  454.         part = TrackControl(termPtr->fHorizScroll, point, 
  455.                         (ProcPtr)HorizScrollTextTermWindow);
  456.     }
  457. } /*DoHorizScrollTermWindow*/
  458.  
  459.  
  460.  
  461. /********************************************************************************
  462.     Procedure:    AdjustVertScrollTermWindow
  463.     Purpose:    Adjusts the vert scroll bar
  464.     Passed:        termPtr:
  465.                     A pointer to the common structure
  466.     Returns:    void
  467. ********************************************************************************/
  468. void    AdjustVertScrollTermWindow(TermWindowPtr termPtr)
  469. {
  470.     short        oldScroll,
  471.                 newScroll,
  472.                 maxTop;
  473.     Rect        ourVisRect;
  474.  
  475.     
  476.     maxTop = (termPtr->fTermEnvirons.textRows) - 
  477.         TermWindowSizeInLines(termPtr);
  478.     
  479.     if (maxTop <= 0) {
  480.         maxTop = 0;
  481.         HiliteControl(termPtr->fVertScroll, 255);        //inactive
  482.     } else {
  483.         if (maxTop > termPtr->fTermEnvirons.textRows) {
  484.             maxTop = termPtr->fTermEnvirons.textRows;
  485.         }
  486.         
  487.         HiliteControl(termPtr->fVertScroll, 0);            //active
  488.     }
  489.  
  490.     SetCtlMax(termPtr->fVertScroll, maxTop);
  491.  
  492.     ourVisRect = (**(termPtr->fTermHandle)).visRect;
  493.     CellRectToPixelRect(termPtr, &ourVisRect);
  494.     
  495.     oldScroll = ourVisRect.top - (**(termPtr->fTermHandle)).viewRect.top;
  496.     newScroll = (GetCtlValue(termPtr->fVertScroll)) * 
  497.                     (termPtr->fTermEnvirons.cellSize.v);
  498.     
  499.     //TMScroll(termPtr->fTermHandle, 0, (oldScroll - newScroll));
  500. } /*AdjustVertScrollTermWindow*/
  501.  
  502.  
  503.  
  504. /********************************************************************************
  505.     Procedure:    VertScrollTextTermWindow
  506.     Purpose:    Makes sure that the control movement happens correctly and the
  507.                     text is scrolled.
  508.     Passed:        termPtr:
  509.                     A pointer to the common structure
  510.     Returns:    void
  511. ********************************************************************************/
  512. pascal    void    VertScrollTextTermWindow(ControlHandle theControl, short part)
  513. {
  514.     short            delta,
  515.                     oldValue;
  516.     TermWindowPtr    termPtr;
  517.     
  518.     
  519.     termPtr = (TermWindowPtr)GetCRefCon(theControl);
  520.  
  521.     oldValue = GetCtlValue(termPtr->fVertScroll);
  522.         
  523.     switch (part) {
  524.         case inUpButton:
  525.         case inDownButton:
  526.             delta = 1;
  527.             break;
  528.  
  529.         case inPageUp:
  530.         case inPageDown:
  531.             delta = TermWindowSizeInLines(termPtr);
  532.             break;
  533.         
  534.         default:
  535.             break;
  536.     }
  537.     
  538.     if (part != 0) {
  539.         if ((part == inDownButton) || (part == inPageDown)) {
  540.             delta = -delta;
  541.         }
  542.         
  543.         CommonActionTermWindow(termPtr->fVertScroll, &delta);
  544.         
  545.         TMScroll(termPtr->fTermHandle, 0, 
  546.             (delta) * (termPtr->fTermEnvirons.cellSize.v));
  547.     }
  548. } /*VertScrollTextTermWindow*/
  549.  
  550.  
  551.  
  552. /********************************************************************************
  553.     Procedure:    DoVertScrollTermWindow
  554.     Purpose:    Does the vert scroll
  555.     Passed:        termPtr --    A pointer to the common structure
  556.                 part --        What part of the scroll the user clicked in
  557.                 point --    Exact point where the click occurred
  558.     Returns:    void
  559. ********************************************************************************/
  560. void     DoVertScrollTermWindow(TermWindowPtr termPtr, short part, Point point)
  561. {
  562.     short        controlValue;
  563.     
  564.     
  565.     if (part == inThumb) {
  566.         controlValue = GetCtlValue(termPtr->fVertScroll);
  567.         
  568.         part = TrackControl(termPtr->fVertScroll, point, nil);
  569.         if (part != 0) {
  570.             controlValue -= GetCtlValue(termPtr->fVertScroll);
  571.             if (controlValue < 0) {
  572.                 TMScroll(termPtr->fTermHandle, 0, 
  573.                     (controlValue) * (termPtr->fTermEnvirons.cellSize.v)
  574.                     );
  575.             }
  576.             if (controlValue > 0) {
  577.                 TMScroll(termPtr->fTermHandle, 0, 
  578.                     (controlValue) * (termPtr->fTermEnvirons.cellSize.v)
  579.                     );
  580.             }
  581.         }
  582.         
  583.         AdjustVertScrollTermWindow(termPtr);
  584.     } else {
  585.         part = TrackControl(termPtr->fVertScroll, point, 
  586.                         (ProcPtr)VertScrollTextTermWindow);
  587.     }
  588. } /*DoVertScrollTermWindow*/
  589.  
  590.  
  591.  
  592. /********************************************************************************
  593.     Procedure:    ContentClickTermWindow
  594.     Purpose:    Handles content clicks in the terminal region
  595.     Passed:        termPtr --        A pointer to the common structure
  596.                 theEventPtr --    Event record containing event
  597.     Returns:    void
  598. ********************************************************************************/
  599. void ContentClickTermWindow(TermWindowPtr termPtr, const EventRecord *theEventPtr)
  600. {
  601.     short            thePart;
  602.     Point            thePoint;
  603.     ControlHandle    theControl;
  604.     Rect            tempRect;
  605.     
  606.     
  607.     if ((WindowPtr)termPtr != FrontWindow()) {
  608.         SelectWindow ((WindowPtr)termPtr);
  609.     } else {
  610.         thePoint = theEventPtr->where;
  611.         GlobalToLocal(&thePoint);
  612.         
  613.         thePart = FindControl(thePoint, (WindowPtr)termPtr, &theControl);
  614.         
  615.             //the user clicked in the vertical scroll bar.  We dispatch here
  616.             //    to the set of vertical handlers.  
  617.         if (theControl == termPtr->fVertScroll) {
  618.             DoVertScrollTermWindow(termPtr, thePart, thePoint);
  619.         } else {
  620.                 //maybe the user clicked in the horizontal scroller?
  621.             if (theControl == termPtr->fHorizScroll) {
  622.                 DoHorizScrollTermWindow(termPtr, thePart, thePoint);
  623.             } else {
  624.                     //Must be a content click in the terminal region.  We'll
  625.                     //    let the terminal tool handle by calling TMClick.
  626.                 if (nil == theControl) {
  627.                     tempRect = (**(termPtr->fTermHandle)).visRect;
  628.                     CellRectToPixelRect(termPtr, &tempRect);
  629.                     if (PtInRect(thePoint, &tempRect)) {
  630.                         TMClick(termPtr->fTermHandle, theEventPtr);                    
  631.                     }
  632.                 }
  633.             }
  634.         }
  635.     }
  636. } /*ContentClickTermWindow*/
  637.  
  638.  
  639.  
  640. /********************************************************************************
  641.     Procedure:    DragTermWindow
  642.     Purpose:    Selects the window if it's not frontmost or calls the toolbox
  643.                     routine DragWindow for the window movement, then updates
  644.                     the window and scroll bars
  645.     Passed:        termPtr --        A pointer to the common structure
  646.                 where --        What point of the window was clicked
  647.     Returns:    void
  648. ********************************************************************************/
  649. void DragTermWindow(TermWindowPtr termPtr, Point where)
  650. {
  651.     Rect        limitRect;
  652.     
  653.     
  654.     if ((WindowPtr)termPtr != FrontWindow()) {
  655.         SelectWindow ((WindowPtr)termPtr);
  656.     } else {
  657.         SetRect(&limitRect, 0, 20, qd.screenBits.bounds.right, 
  658.             qd.screenBits.bounds.bottom);
  659.         
  660.         InsetRect(&limitRect, 4, 4);
  661.         
  662.         DragWindow((WindowPtr)termPtr, where, &qd.screenBits.bounds);
  663.     }
  664. } /*DragTermWindow*/
  665.  
  666.  
  667.  
  668. /********************************************************************************
  669.     Procedure:    ResizeTermWindow
  670.     Purpose:    Selects the window if it's not frontmost or handles size 
  671.                     changes for the window
  672.     Passed:        termPtr --        A pointer to the common structure
  673.                 where --        The point where the user clicked
  674.     Returns:    void
  675. ********************************************************************************/
  676. void ResizeTermWindow(TermWindowPtr termPtr, Point where)
  677. {
  678.     long        newSize;
  679.     Rect        limitRect;
  680.     
  681.     
  682.     if ((WindowPtr)termPtr != FrontWindow()) {
  683.         SelectWindow ((WindowPtr)termPtr);
  684.     } else {
  685.         SetRect(&limitRect, termPtr->fMinWindowSize.h, termPtr->fMinWindowSize.v, 
  686.             (qd.screenBits.bounds.right -  qd.screenBits.bounds.left),
  687.             (qd.screenBits.bounds.bottom -  qd.screenBits.bounds.top) - 20
  688.             );
  689.             
  690.         newSize = GrowWindow((WindowPtr)termPtr, where, &limitRect);
  691.     
  692.         if (0 != newSize) {
  693.             EraseRect(&((WindowPtr)termPtr)->portRect);
  694.             
  695.             SizeWindow((WindowPtr)termPtr, LoWrd(newSize), HiWrd(newSize), true);
  696.             
  697.             limitRect = ((WindowPtr)termPtr)->portRect;
  698.             AdjustTermRect(&limitRect);
  699.             TMResize(termPtr->fTermHandle, &limitRect);
  700.             
  701.             InvalRect(&((WindowPtr)termPtr)->portRect);
  702.         }
  703.     }
  704. } /*ResizeTermWindow*/
  705.  
  706.  
  707.  
  708. /********************************************************************************
  709.     Procedure:    ZoomTermWindow
  710.     Purpose:    Selects the window if it's not frontmost or handles zoom events 
  711.                     by calling the toolbox proc ZoomWindow
  712.     Passed:        termPtr --        A pointer to the common structure
  713.                 where --        The point where the user clicked so we can 
  714.                                     call TrackBox
  715.     Returns:    void
  716. ********************************************************************************/
  717. void ZoomTermWindow(TermWindowPtr termPtr, short zoomFactor, Point where)
  718. {
  719.     Rect        limitRect;
  720.     
  721.     
  722.     if ((WindowPtr)termPtr != FrontWindow()) {
  723.         SelectWindow ((WindowPtr)termPtr);
  724.     } else {
  725.         if (TrackBox((WindowPtr)termPtr, where, zoomFactor)) {
  726.             EraseRect(&((WindowPtr)termPtr)->portRect);
  727.             
  728.             ZoomWindow((WindowPtr)termPtr, zoomFactor, false);
  729.             
  730.             limitRect = ((WindowPtr)termPtr)->portRect;
  731.             AdjustTermRect(&limitRect);
  732.             TMResize(termPtr->fTermHandle, &limitRect);
  733.             
  734.             InvalRect(&((WindowPtr)termPtr)->portRect);
  735.         }
  736.     }
  737. } /*ZoomTermWindow*/
  738.  
  739.  
  740.  
  741. /********************************************************************************
  742.     Procedure:    MouseDownTermWindow
  743.     Purpose:    Click dispatcher for this window type.  
  744.     Passed:        termPtr --        A pointer to the common structure
  745.                 theEventPtr --    Pointer to the event record containing the 
  746.                                     event information.
  747.     Returns:    void
  748. ********************************************************************************/
  749. void MouseDownTermWindow(TermWindowPtr termPtr, const EventRecord *theEventPtr)
  750. {
  751.     short            part;
  752.     long            menuItem;
  753.     WindowPtr        whichWindow;
  754.  
  755.  
  756.     part = FindWindow(theEventPtr->where, &whichWindow);
  757.     
  758.     if (whichWindow != nil) {
  759.         switch (part) {
  760.             case inMenuBar:
  761.                 menuItem = MenuSelect(theEventPtr->where);
  762.                 TMMenu(termPtr->fTermHandle, HiWrd(menuItem), LoWrd(menuItem));
  763.                 break;
  764.                 
  765.             case inContent:
  766.                 ContentClickTermWindow(termPtr, theEventPtr);
  767.                 break;
  768.  
  769.             case inDrag:
  770.             case inGoAway:
  771.                 DragTermWindow(termPtr, theEventPtr->where);
  772.                 FixVertScrollTermWindow(termPtr);
  773.                 FixHorizScrollTermWindow(termPtr);
  774.                 break;
  775.                 
  776.             case inGrow:
  777.                 ResizeTermWindow(termPtr, theEventPtr->where);
  778.                 FixVertScrollTermWindow(termPtr);
  779.                 FixHorizScrollTermWindow(termPtr);
  780.                 break;
  781.             
  782.             case inZoomIn:
  783.             case inZoomOut:
  784.                 ZoomTermWindow(termPtr, part, theEventPtr->where);
  785.                 FixVertScrollTermWindow(termPtr);
  786.                 FixHorizScrollTermWindow(termPtr);
  787.                 break;
  788.         }
  789.     
  790.         AdjustVertScrollTermWindow(termPtr);
  791.         AdjustHorizScrollTermWindow(termPtr);
  792.     }
  793. } /*MouseDownTermWindow*/
  794.  
  795.  
  796.  
  797. /********************************************************************************
  798.     Procedure:    WriteToTermWindow
  799.     Purpose:    This routine will TMStream data to our emulation region.  
  800.     Passed:        termPtr:        Pointer to our storage area (also is a WindowPtr)
  801.                 theData:        ptr to the data
  802.                 lengthOfData:    ptr to long indicating how long data is.
  803.     Returns:    OSErr to indicate an error.
  804. ********************************************************************************/
  805. pascal    OSErr    WriteToTermWindow(TermWindowPtr termPtr, Ptr theData, 
  806.                         Size *lengthOfData)
  807. {
  808.     OSErr            result = noErr;
  809.     long            bytesWritten;
  810.     GrafPtr            savedPort;
  811.  
  812.  
  813.     if (nil != termPtr) {
  814.         GetPort(&savedPort);
  815.         SetPort((GrafPtr)termPtr);
  816.         
  817.         if (nil != (termPtr->fTermHandle)) {
  818.             if ((*lengthOfData) == (bytesWritten = TMStream(termPtr->fTermHandle, 
  819.                                                         theData, 
  820.                                                         (*lengthOfData), 
  821.                                                         cmFlagsEOM)
  822.                                                         )) {
  823.                 TMIdle(termPtr->fTermHandle);
  824.  
  825.                 AdjustVertScrollTermWindow(termPtr);
  826.             } else {
  827.                 result = tmGenericError;
  828.                 DebugStr("\p unable to write to window!.");
  829.             }
  830.             
  831.         SetPort(savedPort);
  832.         } else {
  833.             result = tmGenericError;
  834.             DebugStr("\p theTerminal is nil!");
  835.         }
  836.     } else {
  837.         result = tmGenericError;
  838.         DebugStr("\p WindowPtr is nil!");
  839.     }
  840.     
  841.     return (result);
  842. } /*WriteToTermWindow*/
  843.  
  844.  
  845.  
  846. /********************************************************************************
  847.     Procedure:    FillTermWindow
  848.     Purpose:    Just a quick way to fill the terminal screen
  849.     Passed:        termPtr --        A pointer to the common structure
  850.     Returns:    void
  851. ********************************************************************************/
  852. pascal    void    FillTermWindow(TermWindowPtr termPtr)
  853. {
  854.     OSErr            result                = noErr;
  855.     long            i, 
  856.                     sLength;
  857.     char            cTempString[256];
  858.  
  859.  
  860.     for (i = 0L; i < 10; i++) {
  861.         sprintf(cTempString, "Ain't coding a blast?, loop# %ld\n\r", i);
  862.         sLength = strlen(cTempString);
  863.         WriteToTermWindow(termPtr, cTempString, &sLength);
  864.     }
  865. } /*FillTermWindow*/
  866.  
  867.  
  868.  
  869. /********************************************************************************
  870.     Procedure:    NewTermWindow
  871.     Purpose:    This routine is used to determine initial window placement and
  872.                     characteristics.  
  873.     Passed:        termPtr --            A pointer to the common structure, normally
  874.                                         defined ahead of time for application
  875.                                         convenience
  876.                 boundsRect --        Bounding rectangle for the screen location
  877.                                         of the terminal window.
  878.                 title --            Window title
  879.                 visible --            Determines initial window visibility
  880.                 theProc --            This is the procID which determines window
  881.                                         type.  Since we always attach scroll
  882.                                         bars, it's best that you use a normal 
  883.                                         Macintosh document. 
  884.                 behind --            Use this parameter to determine which 
  885.                                         window this window should appear 
  886.                                         behind.  Pass -1 for frontmost.
  887.                 goAwayFlag --        Display a close box?
  888.                 toolName --            Terminal tool name.  
  889.     Returns:    An OSErr(or) indicating any failure.  
  890. ********************************************************************************/
  891. pascal    OSErr        NewTermWindow(TermWindowPtr *termPtr,
  892.                         const Rect *boundsRect, 
  893.                         ConstStr255Param title, 
  894.                         Boolean visible,
  895.                         short theProc, 
  896.                         WindowPtr behind,
  897.                         Boolean goAwayFlag,
  898.                         Str31 toolName)
  899. {
  900.     OSErr            result                = noErr;
  901.     short            procID,
  902.                     realWindowProcID;
  903.     GrafPtr            savedPort;
  904.     WindowPtr        frWindow = FrontWindow();
  905.     Rect            termRect,
  906.                     realWindowRect = { 0, 0, 0, 0 };
  907.     Str255            realWindowTitle;
  908.     Str255            realToolName;
  909.  
  910.  
  911.     realWindowProcID = theProc;
  912.     if (IsNOTAWindowProc(theProc)) {
  913.         realWindowProcID = zoomDocProc;
  914.     }
  915.     
  916.     if (nil == (*termPtr)) {
  917.         if (nil != ((*termPtr) = (TermWindowPtr)NewPtrClear(sizeof(TermWindowRec)))) {
  918.             (*termPtr)->fWindowType = 99;
  919.         } else {
  920.             DebugStr("\p Error @NewPtr;dw MemErr;dw ResErr");
  921.             return result;
  922.         }
  923.         DebugStr("\p fWindowRecord was nil so we allocated a ptr here.");
  924.     }
  925.     
  926.         //if we have a window to put this behind.
  927.     if (nil != frWindow) {
  928.             //because realWindowRect is empty now, we can make this comparison
  929.         if (EmptyRect(boundsRect)) {
  930.             realWindowRect = (frWindow->portRect);
  931.         } else {
  932.             realWindowRect = *boundsRect;
  933.         }
  934.     } else {
  935.         realWindowRect = qd.screenBits.bounds;
  936.     }
  937.     
  938.         //if we have a have a non-empty string use it.
  939.     BlockMove(title, realWindowTitle, title[0] + 1);
  940.     if (title[0] == 0) {
  941.         BlockMove("\pStatus", (Ptr)title, 7);
  942.         //strcpy(realWindowTitle, "\pStatus");
  943.     }
  944.     
  945.         //arbitrary numbers for the window size.
  946.     //(*termPtr)->fMinWindowSize.h = realWindowRect.right - realWindowRect.left;
  947.     //(*termPtr)->fMinWindowSize.v = realWindowRect.bottom - realWindowRect.top;
  948.     (*termPtr)->fMinWindowSize.v = 150;
  949.     (*termPtr)->fMinWindowSize.h = 150;
  950.     
  951.     if (nil != (NewWindow((*termPtr), 
  952.                             &realWindowRect,
  953.                             realWindowTitle,
  954.                             false,
  955.                             realWindowProcID,
  956.                             behind,
  957.                             goAwayFlag,
  958.                             0L
  959.                         ))) {
  960.         GetPort(&savedPort);
  961.         SetPort((GrafPtr)(*termPtr));
  962.         
  963.         if (nil != ((*termPtr)->fVertScroll = NewControl(
  964.                                                 (WindowPtr)(*termPtr), 
  965.                                                 &((WindowPtr)*termPtr)->portRect, 
  966.                                                 "\p", 
  967.                                                 true, 
  968.                                                 0, 
  969.                                                 0, 
  970.                                                 0, 
  971.                                                 scrollBarProc, 
  972.                                                 (long)(*termPtr)
  973.                                             ))) {
  974.             if (nil != ((*termPtr)->fHorizScroll = NewControl(
  975.                                                     (WindowPtr)(*termPtr), 
  976.                                                     &((WindowPtr)*termPtr)->portRect, 
  977.                                                     "\p", 
  978.                                                     true, 
  979.                                                     0, 
  980.                                                     0, 
  981.                                                     0, 
  982.                                                     scrollBarProc, 
  983.                                                     (long)(*termPtr)
  984.                                                 ))) {
  985.                 FixVertScrollTermWindow((*termPtr));
  986.                 FixHorizScrollTermWindow((*termPtr));
  987.         
  988.                 BlockMove(toolName, realToolName, toolName[0] + 1);
  989.                 //strncpy(realToolName, toolName, toolName[0] + 1);
  990.                 if (toolName[0] == 0) {
  991.                     BlockMove("\pVT102 Tool", realToolName, 10);
  992.                     //strcpy(realToolName, "\pTTY Tool");
  993.                 }
  994.             
  995.                 procID = TMGetProcID(realToolName);
  996.                 if (-1 == procID) {
  997.                     CRMGetIndToolName(classTM, 1, realToolName);
  998.                 }
  999.                 
  1000.                 termRect = ((WindowPtr)*termPtr)->portRect;
  1001.                 AdjustTermRect(&termRect);
  1002.                 
  1003.                 if (nil != ((*termPtr)->fTermHandle = 
  1004.                                 TMNew(&termRect,
  1005.                                         &termRect,
  1006.                                         0L,
  1007.                                         procID,
  1008.                                         (WindowPtr)(*termPtr),
  1009.                                         nil,
  1010.                                         nil,
  1011.                                         nil,
  1012.                                         nil,
  1013.                                         nil,
  1014.                                         0L,
  1015.                                         0L
  1016.                                     ))) {
  1017.                     (*termPtr)->fTermEnvirons.version = curTermEnvRecVers;
  1018.                     if (noErr == (result = TMGetTermEnvirons((*termPtr)->fTermHandle,
  1019.                             &((*termPtr)->fTermEnvirons)))) {
  1020.                     }
  1021.                 } else {
  1022.                     DebugStr("\p Err at TMNew");
  1023.                     result = tmGenericError;
  1024.                 }
  1025.             } else {
  1026.                 DebugStr("\p Err at NewControl");
  1027.                 result = tmGenericError;
  1028.             }
  1029.         } else {
  1030.             DebugStr("\p Err at NewControl");
  1031.             result = tmGenericError;
  1032.         }
  1033.             
  1034.         if(visible)
  1035.             ShowWindow((WindowPtr)*termPtr);
  1036.             
  1037.         SetPort(savedPort);
  1038.     } else {
  1039.         DebugStr("\p Err at NewWindow");
  1040.         result = tmGenericError;
  1041.     }
  1042.     
  1043.     return (result);
  1044. } /*NewTermWindow*/
  1045.  
  1046.  
  1047.  
  1048. /********************************************************************************
  1049.     Procedure:    IsTermWindowEvent
  1050.     Purpose:    This routine peeks at the passed event record fields to determine
  1051.                     if the event should be destined for this window.  I use 
  1052.                     Boolean IFs when peeking at the event record to save a few 
  1053.                     instructions instead of the switch C token.
  1054.     Passed:        termPtr --            A pointer to the common structure
  1055.                 theEventPtr --        Event record containing the current event
  1056.     Returns:    True if the event is for our window.
  1057. ********************************************************************************/
  1058. pascal    Boolean        IsTermWindowEvent(TermWindowPtr termPtr, 
  1059.                             const EventRecord *theEventPtr)
  1060. {
  1061.     Boolean                result = false;
  1062.     short                part;
  1063.     WindowPtr            whichWindow;
  1064.     
  1065.     
  1066.     if (nil != termPtr) {
  1067.         if (nil != (termPtr->fTermHandle)) {
  1068.             TMIdle(termPtr->fTermHandle);
  1069.         }
  1070.     
  1071.         if (mouseDown == (theEventPtr->what)) {
  1072.             part = FindWindow(theEventPtr->where, &whichWindow);
  1073.             if (whichWindow == (WindowPtr)termPtr) {
  1074.                 result = true;
  1075.             }
  1076.         } else {
  1077.             if ((updateEvt == (theEventPtr->what)) ||
  1078.                         (activateEvt == (theEventPtr->what))) {
  1079.                 if (theEventPtr->message == (long)termPtr) {
  1080.                     result = true;
  1081.                 }
  1082.             }
  1083.         }
  1084.     }
  1085.     
  1086.     return (result);
  1087. } /*IsTermWindowEvent*/
  1088.  
  1089.  
  1090.  
  1091. /********************************************************************************
  1092.     Procedure:    HandleTermWindowEvent
  1093.     Purpose:    This is a basic dispatcher of the event.  Since in a normal 
  1094.                     implementation of this function it only gets called if the 
  1095.                     routine is actually needed, many checks to verify the 
  1096.                     window are avoided.
  1097.     Passed:        termPtr --            A pointer to the common structure
  1098.                 theEventPtr --        Event record containing the current event
  1099.     Returns:    void
  1100. ********************************************************************************/
  1101. pascal    void    HandleTermWindowEvent(TermWindowPtr termPtr, 
  1102.                         const EventRecord *theEventPtr)
  1103. {
  1104.     Boolean            activate;
  1105.     GrafPtr            savedPort;
  1106.  
  1107.  
  1108.     if (nil != termPtr) {
  1109.         GetPort(&savedPort);
  1110.         SetPort((GrafPtr)termPtr);
  1111.         
  1112.         if (nil != (termPtr->fTermHandle)) {
  1113.             switch (theEventPtr->what) {
  1114.                 case mouseDown:
  1115.                     MouseDownTermWindow(termPtr, theEventPtr);
  1116.                     break;
  1117.                     
  1118.                 case activateEvt:
  1119.                     activate = (0 != (theEventPtr->modifiers & activeFlag));
  1120.                     TMActivate(termPtr->fTermHandle, activate);
  1121.                     if (activate) {
  1122.                         DrawGrowIcon((WindowPtr)termPtr);
  1123.                         DrawControls((WindowPtr)termPtr);
  1124.                         
  1125.                         AdjustVertScrollTermWindow(termPtr);
  1126.                         AdjustHorizScrollTermWindow(termPtr);
  1127.                     }    
  1128.                     break;
  1129.                     
  1130.                 case updateEvt:
  1131.                     BeginUpdate((WindowPtr)termPtr);
  1132.                         if (nil != ((WindowPtr)termPtr)->visRgn) {
  1133.                             TMUpdate(termPtr->fTermHandle, ((WindowPtr)termPtr)->visRgn);
  1134.                             
  1135.                             DrawGrowIcon((WindowPtr)termPtr);
  1136.                             DrawControls((WindowPtr)termPtr);
  1137.                         }
  1138.                     EndUpdate((WindowPtr)termPtr);
  1139.                     break;
  1140.                     
  1141.                 default:
  1142.                     break;
  1143.             }
  1144.         } else {
  1145.             DebugStr("\p theTerminal is nil! at HandleTermWindowEvent");
  1146.         }
  1147.         
  1148.         SetPort(savedPort);
  1149.     } else {
  1150.         DebugStr("\p termPtr is nil! at HandleTermWindowEvent");
  1151.     }
  1152. } /*HandleTermWindowEvent*/
  1153.  
  1154.  
  1155.  
  1156. /********************************************************************************
  1157.     Procedure:    DisposeTermWindow
  1158.     Purpose:    This routine disposes of all private storage for our window.  You
  1159.                     can avoid this step if you simply _ExitToShell
  1160.     Passed:        termPtr --            A pointer to the common structure
  1161.     Returns:    void
  1162. ********************************************************************************/
  1163. pascal    void    DisposeTermWindow(TermWindowPtr termPtr)
  1164. {
  1165.     if (nil != termPtr) {
  1166.         if (nil != termPtr->fVertScroll) {
  1167.             DisposeControl(termPtr->fVertScroll);
  1168.             termPtr->fVertScroll = nil;
  1169.             
  1170.             if (nil != termPtr->fHorizScroll) {
  1171.                 DisposeControl(termPtr->fHorizScroll);
  1172.                 termPtr->fHorizScroll = nil;
  1173.                 
  1174.                 if (nil != (termPtr->fTermHandle)) {
  1175.                     TMDispose(termPtr->fTermHandle);
  1176.                     termPtr->fTermHandle = nil;
  1177.                 } else {
  1178.                     DebugStr("\p theTerminal is nil!");
  1179.                 }
  1180.             } else {
  1181.                 DebugStr("\p fHorizScroll is nil!");
  1182.             }
  1183.         } else {
  1184.             DebugStr("\p fVertScroll is nil!");
  1185.         }
  1186.  
  1187.         DisposeWindow((WindowPtr)termPtr);
  1188.     } else {
  1189.         DebugStr("\p termPtr is nil!");
  1190.     }
  1191. } /*DisposeTermWindow*/
  1192.